import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import {debounce} from "./common/utils";
import toast from 'components/common/toast'
import FastClick from 'fastclick'
import VueLazyload from "vue-lazyload";

// 引入样式
import { Button,Swipe, SwipeItem  } from 'vant';
// 安装vant插件
Vue.use(Button).use(Swipe).use(SwipeItem);

Vue.config.productionTip = false

// 设置bus总线
Vue.prototype.$bus = new Vue()
// 安装插件
Vue.use(toast)

// 解决移动端300ms的延迟问题
FastClick.attach(document.body)

// 图片懒加载
Vue.use(VueLazyload,{
  // 传入占位图片，根据自己的需求在Constructor Options中找对应属性进行操作
  loading:require('./assets/img/common/placeholder.png')
})

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')


// 一、文档结构划分
// 1.src/asserts放css\img\js等
// 2.src/components放公共组件，
  // 细分为common文件夹（可以在其他项目使用的组件）
  // content文件夹（业务相关组件，其他项目不可用）
//3. src/views放相关视图组件，如home等
//4.src\router放路由相关文件
//5. src\store放vuex状态管理相关文件
//6. src\network放网络相关文件
// src\common放公共的js文件，如项目中抽离出来的常量

// 二、引用两个css文件
// base.css基本的css样式
// normalize.css将不同浏览器标签展示进行统一
// 在app.vue进行了引用
// @import "./assets/css/base.css";

// 三、文件别名
// 1.脚手架3因配置文件隐藏较深，所以新建文件vue.config.js文件，在其中配置别名
  // 2.将原来的项目中的.editorconfig放到新建的项目中，用于统一格式

// 四、项目模块划分 tabbar>路由映射关系
// tabbar流程
  // 1.创建tabbar组件（底部大盒子）,设置其展示样式，在其中设置一个插槽，用于向其中添加元素
  // 2.创建tabbarItem组件（tab小盒子），设置其展示样式，
      // 按业务需求在其中设置3个插槽，用于展示状态图标、tab名称（本次采用传入两张图，活跃展示、不活跃展示）
  // 3.创建业务组件，用于向tabbarItem组件插槽中传入内容，传入path，
  // 4.在viwes创建页面视图文件，在路由配置映射关系

  // 五、导航组件navbar创建

  // 六、网络模块封装
  // 安装axios,在network封装request,创建home.js对home进行网络请求封装，用于统一管理
  //在home组件进行调用home.js中的方法，获取数据

// ......

// better-scroll安装使用，示例代码在category中
// npm install better-scroll --save
// 第三方库引用规则，先封装，再使用
// 使用
// 1.定义一个div盒子wrapper，设置高度，注意：weapper中只能有一个元素
// 2.引用import BScroll from 'better-scroll'
// 3.在mounted中new一个Bscroll对象，将wrapper传入
// mounted() {
//   this.scroll=new BScroll(document.querySelector('.wrapper'),{
//   })
// },



// 七.解决可滚动区域重计算问题
//croll对象中的scrollerHeight用于决定可滚动的高度，采用scroll.refresh()可以触发它的重新计算
// 解决方法：监听每张图片的加载，加载一张就进行触发refresh()
// 采用bus总线监听的方法
// ==1.在main.js中
// Vue.prototype.$bus = new Vue()
// ==2.在goodsitem组件中监听图片加载完成事件
// vue中监听图片加载完成采用@load,一旦加载完成就会调用自定义的imageLoad方法
// <img :src="goodsItem.picture" @load="imageLoad">
// ==3.定于imageLoad方法
// methods:{
//   // 图片加载完成回调的函数
//   imageLoad() {
//     // 采用事件总线监听发送事件
//     this.$bus.$emit('itemImageLoad')
//   }
// }
// ==4.在scroll组件中定义触发重计算的方法
// refresh() {
//   // this.scroll &&逻辑语，如果前面为空或者false，就不执行后面的语句
//   this.scroll && this.scroll.refresh()
// }
// ==5.父组件，如home组件进行监听子组件传递来itemImageLoad事件，监听到就触发回调函数
// 不要在created中进行获取值监听，会出现监听不到的情况
// mounted() {
//   // 监听item中图片加载
//   this.$bus.$on('itemImageLoad',() => {
//     this.$refs.scroll.refresh()
//   })
// },

// 拓展
// 1.原生js监听图片加载完成
// img.onload = function () {
// }
// 2.bus >总线
// 1.Vue.prototype.$bus = new Vue()
// 2提交事件.this.$bus.emit('事件名称',参数)
// 3接收事件，并回调.this.$bus.$on('事件名称'，回调函数)

// 八、防抖debounce/节流throtle
// 方案：封装一个函数，在执行某一个函数之前，搞一个定时器，让要执行的函数等一会再执行
// 1.封装到common的utils.js的工具方法中
// 原理：如果timer有值，就取消它的执行，重新开始计算，当运行到最后一次，timer被取消成为空值时，就会继续执行setTimeout中的代码
// 防抖封装
// func代表要执行的函数，delay要等待的时间
// debounce(func,delay){
//   let timer = null
//   // ...args代表可以传入多个参数
//   return function (...args) {
//     // clearTimeout()方法可取消setTimeout()的执行。
//     // timer在一个闭包中，它对外层的timer进行了引用，所以不会被销毁
//     // setTimeout中的函数在下一次事件循环时才进行执行，不写延时时间也是会放到后面执行
//     if (timer) clearTimeout(timer)
//     timer = setTimeout(() => {
//       func.apply(this,args)
//     },delay)
//   }
// },
// 2.引用
// import {debounce} from "common/utils";
// mounted() {
//       将会频繁调用的函数传递给防抖函数
//   const resresh=debounce(this.$refs.scroll.refresh,500)
//   // 3.监听item中图片加载
//   this.$bus.$on('itemImageLoad',() => {
//     // 执行封装的防抖函数
//     resresh()
//   })
// },

// 九、吸顶效果
// 1.获取要吸顶的组件的offsetTop
// 获取正确的值
//     监听轮播图加载完成
//         加载完成在home组件中获取到正确的值
// 为了不让homeSwiper多次发出事件
// 可以采用isLoad变量进行状态记录，一旦发送过，就不在发送
// 2.监听滚动，动态改变tabControl的样式
// 采用双组件，动画效果，一个组件放在顶部，下拉到一定的位置时显示出来，true展示，false隐藏
// this.isTabFixed = (-position.y) > this.tabOffsetTop

// 十、让home保持离开时的状态
// 1.让home不要随意销毁
// 切换url之后，前一个路由会被销毁,在app.vue中用<keep-alive>包裹router-view就不会触发销毁
// destroyed() {
//   console.log('home路由销毁')
// },
// 2.让home中的内容保持原来的位置
// 离开时(deactivated()离开当前url时)，保存一个位置信息saveY
// 进来时（activated()当前url活跃时），将位置设为原来保存的saveY
// 注意：最好回来时，进行一次refresh


// 时间戳格式化成正常时间
// 1.将时间戳转化成Date对象（时间戳是秒钟，Date需要传入毫秒数，所以需要*1000）
// const date=new Date(1535694719*1000)
// 2.将date进行格式化，转换成对应字符串
// fmt.format(date,'yyyy-MM-dd hh:mm:ss')
// H:24小时制
// h:12小时制

// 混入mixin
// 2个不同的组件，其中的对象有重复的代码时
// 1.类的继承,通过extends进行继承
// class Anim{
//   run () {
//   }
// }
// class Person extends Anim {
//   run () {
//   }
// }
// 2.混入
// 1.在mixin中定义通用代码
// export const itemListenerMixin = {
//   mounted () {
//     // 将会频繁调用的函数传递给防抖函数
//     const resresh=debounce(this.$refs.scroll.refresh,300)
//     // 3.监听item中图片加载
//     this.itemImgListener = () => {
//       resresh()
//     }
//     this.$bus.$on('itemImageLoad',
//       // 封装一个函数，在执行某一个函数之前，搞一个定时器，让要执行的函数等一会再执行
//       // 执行封装的防抖函数
//       this.itemImgListener
//     )
//     console.log('zzxc')
//   }
// }
// 2.在需要用的地方导入
// import {itemListenerMixin} from "common/mixin";
// 3.在组件对象中添加属性
// mixins:[itemListenerMixin],
// 那么在组件的mounted函数运行时会自动包括混入的代码运行


// 重要Polyfill做浏览器适配，如有些浏览器不支持promise，可以采用Polyfill在内部实现一个promise然后，在代码运行时使用的就是实现出来的promise
// Polyfill 是一块代码（通常是 Web 上的 JavaScript），用来为旧浏览器提供它没有原生支持的较新的功能。
// https://blog.csdn.net/C_ZhangSir/article/details/102490761


// 解决移动端延迟点击300ms的问题
// 1.安装
// npm install fastclick --save
// 2.在main.js导入
// import FastClick from 'fastclick'
// 3.调用attach方法
// 解决移动端300ms的延迟问题
// FastClick.attach(document.body)


// 图片懒加载，图片进入可视界面范围时，加载出图片
// https://github.com/hilongjw/vue-lazyload

// 1.安装
// npm i vue-lazyload -S
// import VueLazyload from "vue-lazyload";
// 2.安装，可以传入各种对象属性
// Vue.use(VueLazyload,{
//   // 传入占位图片，根据自己的需求在Constructor Options中找对应属性进行操作
//   loading:require('./assets/img/common/placeholder.png')
// })
// 3.使用，将原先的src属性进行替换
// <img v-lazy='showImage' @load="imageLoad">


// "postcss-px-to-viewport"将px进行转换
// 1.安装
// npm install postcss-px-to-viewport --save-dev
// 2.在postcss.config.js中进行配置

// ngix部署项目
// 1下载安装
// 2.运行方式1：将打包文件放到ngix的html文件夹下
// 2.运行方式2：修改配置文件，找到ngix.config文件，修改路径，注意修改完要重启
// location / {
//   root   html;
//   index  index.html index.htm;
// }



// vue响应式原理
// const app = new Vue({
//   el:'#app',
//   data:{
//     message:'hhh',
//     name:'why'
//   }
// })

// 1.app.message修改数据，vue内部如何监听mesage数据的改变
// object.defineProperty 监听对象属性的改变
  // 0.1.data对象传进去之后，进行遍历，拿到所有的key
  // obj.keys(obj).forEach(key => {
  //   let value = obj[key]
  //
  //   // 0.2采用defineProperty对所有属性进行重新定义，通过定义的set属性进修改后的值设置进去，在通过get获取新的值
  //   obj.defineProperty(obj,key,{
  //     set(newValue) {
  //       console.log('监听'+key+'改变')
  //       // 告诉谁？谁用告诉谁？谁在用？
  //       // 根据解析html代码，获取那些人有用属性
  //       // 张三、李四、王五
  //           dep.notify()
  //       value = newValue
  //     },
  //     get() {
  //       console.log('获取'+key+'对应的值')
  //       // html中的每个用到该值的地方，都会调用get,从而可以知道哪些地方调用get使用了对应值
  //       // 张三：get
  //       // 李四：get
  //       // 王五：get
  //       return value
  //     }
  //   })
  // })
// 2.当数据发生改变，vue如何知道要通知哪些人，界面刷新
// 发布订阅模式
// 发布者
// class Dep {
//   constructor() {
//     记录订阅者
//     this.subs = []
//   }
//   将订阅者加到记录中,传入Watcher对象，添加到订阅者记录中
//   addSub(Watcher) {
//     this.subs.push(Watcher)
//   }
//   一旦调用，就通知所有的订阅者去更新自己的update
//   notify() {
//     this.subs.forEach(item => {
//       item.update()
//     })
//   }
// }
// 订阅者
// 监听观察，通过这个类可以创建出多个对象
// class Watcher {
//   生成订阅者者对象，一个get,就会生成一个
//   constructor(name) {
//     this.name = name
//   }
//   更新订阅的值
//   update() {
//     console.log(this.name + 'update')
//   }
// }
// const dep = new Dep()
//
// 谁调用get,就调用Watcher对象，此代码放在get中
// const w1 = new Watcher('张三')
// dep.addSub(w1)
//
// const w2 = new Watcher('张三1')
// dep.addSub(w2)
//
// 一旦发生改变，在set方法中调用notify方法进行通知
// dep.notify()
